package com.zsj.juc.completableFuture;

import lombok.*;
import lombok.experimental.Accessors;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author zsj
 * @version 1.0
 * @date 2024/4/18 18:37
 * @description 为Future接口的升级
 */
public class CompletableFutureMallTest {
    /*
     *  completableFuture.get()和completableFuture.join()
     *  两个方法有什么区别
     *  基本是一样的 区别在于get()在运行时会抛出检查型异常
     *  而join不会
     */

    static List<NetMall> list = Arrays.asList(
            new NetMall("京东"),
            new NetMall("淘宝"),
            new NetMall("当当")
    );

    /**
     * step by step 一个一个查
     *
     * @param list        商家列表
     * @param productName 商品名称
     * @return 返回各个平台商品价格
     */
    public static List<String> getPrice(List<NetMall> list, String productName) {
        return list.stream().map(n ->
                        String.format(productName + "in %s is %.2f",
                                n.getNetMallName(),
                                n.calcPrice(productName)))
                .collect(Collectors.toList());
    }

    /**
     * 异步编程
     *
     * @param list        商家列表
     * @param productName 商品名称
     * @return
     */
    public static List<String> getPriceByCompletableFuture(List<NetMall> list,
                                                           String productName) {
        return list.stream()
                .map(n ->
                        CompletableFuture.supplyAsync(
                                () -> String.format(productName + "in %s is %.2f",
                                        n.getNetMallName(),
                                        n.calcPrice(productName))))
                .collect(Collectors.toList())
                .stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList());
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        List<String> mysql = getPrice(list, "mysql");
        mysql.forEach(System.out::println);
        long end = System.currentTimeMillis();
        System.out.println("消耗时间" + (end - start) + "毫秒");


        long start2 = System.currentTimeMillis();
        List<String> mysql1 = getPriceByCompletableFuture(list, "mysql");
        mysql1.forEach(System.out::println);
        long end2 = System.currentTimeMillis();
        System.out.println("消耗时间" + (end2 - start2) + "毫秒");
    }
}

class NetMall {
    @Getter
    private String netMallName;

    public NetMall(String netMallName) {
        this.netMallName = netMallName;
    }

    public double calcPrice(String productName) {
        try {
            TimeUnit.MILLISECONDS.sleep(1000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Accessors(chain = true)
class Student {
    private Integer id;
    private String studentName;
    private String major;
}